package com.chatplus.application.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.common.util.OkHttpClientUtil;
import com.chatplus.application.domain.dto.ExtendConfigDto;
import com.xingyuv.captcha.util.MD5Util;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 百度翻译工具
 */
public class BaiduTransUtil {

    private BaiduTransUtil() {
    }

    private static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(BaiduTransUtil.class);
    private static final String TRANS_API_HOST = "https://fanyi-api.baidu.com/api/trans/vip/translate";
    private static String appid;
    private static String securityKey;

    /**
     * 获取翻译结果
     *
     * @param query 请求翻译query
     * @param from  翻译源语言
     * @param to    翻译目标语言
     *              query 长度：为保证翻译质量，请将单次请求长度控制在 6000 bytes以内（汉字约为输入参数 2000 个）
     * @return 翻译结果
     */
    public static String getTransResult(String query, String from, String to) {
        ExtendConfigDto extendConfigDto = ConfigUtil.getExtendConfig();
        appid = extendConfigDto.getBaiduTransAppId();
        securityKey = extendConfigDto.getBaiduTransSecurityKey();
        if (StringUtils.isEmpty(query) || StringUtils.isEmpty(appid) || StringUtils.isEmpty(securityKey)) {
            return query;
        }
        if (query.getBytes().length > 6000) {
            LOGGER.message("翻译文本过长,跳过翻译").context("query", query).context("length", query.length()).error();
            return query;
        }
        if (StringUtils.isEmpty(from)) {
            from = "auto";
        }
        if (StringUtils.isEmpty(to)) {
            to = "zh";
        }
        Map<String, String> params = buildParams(query, from, to);
        OkHttpClient okHttpClient = OkHttpClientUtil.getOkHttpClient(null, true);
        Request request = new Request.Builder()
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .url(getUrlWithQueryString(params))
                .get()
                .build();
        Call call = okHttpClient.newCall(request);
        try (Response response = call.execute()) {

            if (response.isSuccessful() && response.body() != null) {
                String result = response.body().string();
                JSONObject jsonObject = JSONUtil.parseObj(result);
                if (jsonObject.containsKey("error_code")) {
                    LOGGER.message("翻译失败").context("query", query).context("result", result).error();
                    return query;
                }
                return jsonObject.getJSONArray("trans_result").getJSONObject(0).getStr("dst");
            }
        } catch (Exception e) {
            LOGGER.message("翻译失败").exception(e).error();
        }
        return query;
    }

    public static String getUrlWithQueryString(Map<String, String> params) {
        String url = TRANS_API_HOST;
        if (params == null) {
            return url;
        }

        StringBuilder builder = new StringBuilder(url);
        builder.append("?");
        int i = 0;
        for (String key : params.keySet()) {
            String value = params.get(key);
            if (value == null) { // 过滤空的key
                continue;
            }
            if (i != 0) {
                builder.append('&');
            }
            builder.append(key);
            builder.append('=');
            builder.append(URLEncoder.encode(value, StandardCharsets.UTF_8));
            i++;
        }

        return builder.toString();
    }

    private static Map<String, String> buildParams(String query, String from, String to) {
        Map<String, String> params = new HashMap<String, String>();
        params.put("q", query);
        params.put("from", from);
        params.put("to", to);

        params.put("appid", appid);
        // 随机数
        String salt = String.valueOf(System.currentTimeMillis());
        params.put("salt", salt);
        // 签名
        String src = appid + query + salt + securityKey; // 加密前的原文
        params.put("sign", MD5Util.md5(src));
        return params;
    }
}
